﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CodePlex.KeyedList
{
	/// <summary>
	/// Represents a Key value that consist of multible values
	/// </summary>
	/// <typeparam name="T1">Key type 1</typeparam>
	/// <typeparam name="T2">Key type 2</typeparam>
	public struct Key<T1, T2> : IEquatable<Key<T1, T2>>
	{

		static Key()
		{
			_comparer = new KeyEqualityComparer<T1, T2>();
		}

		private static KeyEqualityComparer<T1, T2> _comparer;
		
		/// <summary>
		/// Comparer that will compare the internal values
		/// </summary>
		public static KeyEqualityComparer<T1, T2> Comparer
		{
			get { return Key<T1, T2>._comparer; }
		}
		
		/// <summary>
		/// Returns a new instance of this class
		/// </summary>
		/// <param name="keyValue1"></param>
		/// <param name="keyValue2"></param>
		public Key(T1 keyValue1, T2 keyValue2)
		{
			_keyValue1 = keyValue1;
			_keyValue2 = keyValue2;
		}

		private T1 _keyValue1;
		private T2 _keyValue2;

		/// <summary>
		/// The first key value
		/// </summary>
		public T1 Value1
		{
			get { return _keyValue1; }
		}

		/// <summary>
		/// The second key value
		/// </summary>
		public T2 Value2
		{
			get { return _keyValue2; }
		}

		/// <summary>
		/// Returns the hash code for this instance.
		/// </summary>
		/// <returns></returns>
		public override int GetHashCode()
		{
			return _comparer.GetHashCode(this);
		}


		/// <summary>
		/// Indicates whether the current Key is equal to another Key.
		/// </summary>
		/// <param name="other"></param>
		/// <returns></returns>
		public override bool Equals(object other)
		{
			if(other is Key<T1, T2>)
				return _comparer.Equals(this, (Key<T1, T2>)other);
			return false;
		}

		/// <summary>
		/// Indicates whether the current Key is equal to another Key.
		/// </summary>
		/// <param name="other"></param>
		/// <returns></returns>
		public bool Equals(Key<T1, T2> other)
		{
			return _comparer.Equals(this, other);
		}

		/// <summary>
		/// Indicates whether the current Key is equal to another Key.
		/// </summary>
		/// <param name="other"></param>
		/// <returns></returns>
		bool IEquatable<Key<T1, T2>>.Equals(Key<T1, T2> other)
		{
			return _comparer.Equals(this, other);
		}

	}
}
